from tortoise.expressions import Q, F
import pytz  # 导入时区库
import math

from app.controllers.appointment.list import appointment_list_controller
from app.controllers.goods.sku import sku_controller
from app.controllers.marketing.integral import integral_controller
from app.controllers.marketing.level_integral import level_integral_controller
from app.controllers.orders.wechat import wechat_controller
from app.controllers.saas.buckling import buckling_controller
from app.core.websocket_manager import manager
from app.schemas.saas import BucklingCreate
from app.settings import settings
from app.controllers.customer.users import users_controller
from app.controllers.marketing.coupons import coupons_controller
from app.controllers.marketing.coupons_rule import coupons_rule_controller
from app.controllers.marketing.deposit import deposit_controller
from app.core.crud import CRUDBase
from app.models import GoodsSku, MiniAuditLog, Goods, Deposit, CustomerUser, Coupons, CouponsRole, OrdersReceive, \
    OrdersExpress, OrdersWater, MiniSettings, AppointmentList, Integral, Buckling, LevelIntegral
from app.models.orders import OrdersList, OrdersGoods
from app.schemas.marketing import BaseCommission, BaseDeposit, DepositCreate, CouponsCreate, IntegralCreate, \
    LevelIntegralCreate
from app.schemas.orders import OrdersListCreate, OrdersListUpdate, OrdersGoodsCreate, OrdersGoodsUpdate, \
    OrdersListCreateMini, OrdersListPay
from app.controllers.orders.goods import orders_goods_controller
from datetime import datetime, timedelta
from app.log.log import logger
from tortoise.functions import Sum
from collections import defaultdict
from tortoise.functions import Count, Max, Min
from tortoise.transactions import in_transaction
import random
from app.utils.TaskScheduler import TaskScheduler

scheduler = TaskScheduler()


class OrdersListController(CRUDBase[OrdersList, OrdersListCreate, OrdersListUpdate]):
    def __init__(self):
        super().__init__(model=OrdersList)

    async def do_list(self, page: int, page_size: int, search: Q = Q()):
        query = self.model.filter(search)
        total = await query.count()
        objs = await query.offset((page - 1) * page_size).limit(page_size).order_by('-id')
        data = [await obj.to_dict(exclude_fields=["updated_at", "deleted_at"]) for obj in objs]
        ##获取good详情
        for orders in data:
            goods_q = Q(order_id=orders['id'])
            goods_total, goods_data = await orders_goods_controller.do_list(page=1, page_size=100, search=goods_q)
            orders['goods'] = goods_data
        return total, data

    async def do_detail(self, data_id: int, user_id: int):
        await self.order_timeout(job_id="", order_id=data_id)
        obj = await OrdersList.filter(id=data_id).filter(user_id=user_id).first()
        data = await obj.to_dict()
        ##查一下购买商品详细信息
        goods_q = Q(order_id=data['id'])
        goods_total, goods_data = await orders_goods_controller.do_list(page=1, page_size=100, search=goods_q)
        data['goods'] = goods_data
        if data['status'] == 0:  ##计时器
            now = datetime.now()
            exp_time_str = data['exp_time']
            exp_time = datetime.strptime(exp_time_str, "%Y-%m-%d %H:%M:%S")
            time_diff = exp_time - now
            seconds_diff = time_diff.total_seconds()
        else:
            seconds_diff = 0
        data['last_time'] = int(seconds_diff)
        if data['type'] == 3:
            zs_price = await Deposit.filter(order_id=data_id).first().values()
            if zs_price:
                data['zs_price'] = float(zs_price.get("zs_price"))
        return data

    async def do_total(self, space_id: int):
        now = datetime.now()
        # 今天的开始时间（00:00:00）
        start_of_today = now.replace(hour=0, minute=0, second=0, microsecond=0)
        # 明天的开始时间（00:00:00）
        start_of_tomorrow = start_of_today + timedelta(days=1)

        query = self.model.filter(address_id=space_id, pay_time__gte=start_of_today,
                                  pay_time__lt=start_of_tomorrow, status=1)
        pay_order_count = await query.count()
        pay_order_price_count = await query.filter(is_express=1).annotate(total=Sum("price")).first().values("total")

        return pay_order_count, pay_order_price_count['total']

    async def do_get(self, data_id: int):
        await self.order_timeout(job_id="", order_id=data_id)
        obj = await self.get(id=data_id)
        data = await obj.to_dict()
        ##查一下购买商品详细信息
        goods_q = Q(order_id=data['id'])
        goods_total, goods_data = await orders_goods_controller.do_list(page=1, page_size=100, search=goods_q)
        data['goods'] = goods_data
        if data['type'] == 3:
            zs_price = await Deposit.filter(order_id=data_id).first().values()
            if zs_price:
                data['zs_price'] = float(zs_price.get("zs_price"))
        return data

    ##创建订单
    async def do_create(self, obj_in: OrdersListCreateMini, user_id):
        ##拿到下单redis锁，分布式系统需要
        logger.info("拿到下单redis锁,进入下单流程")
        ##根据sku计算订单合计金额
        type = obj_in.type
        goods = obj_in.sku
        address_id = obj_in.address_id
        price = 0.00

        # 提前拿到所有sku信息,优化
        sku_ids = [good.get('sku_id') for good in goods]
        # 批量查询所有商品的库存和价格信息，减少数据库查询次数
        sku_data = await GoodsSku.filter(id__in=sku_ids).values("id", "sku_level", "sku_kc", "goods_id", "sku_name")
        # 创建一个字典，方便通过 sku_id 查找相应的商品信息
        sku_info_dict = {sku['id']: sku for sku in sku_data}
        logger.info("遍历goods")
        for good in goods:
            sku_id = good.get('sku_id')
            num = good.get('num')
            ##查询目前sku的单价和库存
            sku_now = sku_info_dict.get(sku_id)
            if not sku_now:  # 商品不存在
                return {"pay_status": 0, "msg": "商品不存在"}
            kc_now = sku_now['sku_kc']
            if kc_now < num:  # 库存不足
                return {"pay_status": 0, "msg": f"{sku_now['sku_name']}库存不足,当前库存{kc_now}"}
            ##price_now = sku_now['sku_level']
            price_now = await sku_controller.get_price_by_user(sku_id, user_id)
            logger.info(f"获取会员单价{price_now}")
            price = price + price_now * num
            attr_price = orders_goods_controller.format_attr_price(attr=good.get('attr', None))
            price = price + attr_price * num
            good['goods_id'] = sku_now['goods_id']
            good['sku_name'] = sku_now['sku_name']
            good['price'] = price_now * num + attr_price * num
            good['kc_now'] = kc_now
            good['attr'] = good.get('attr', None)

        ##创建订单
        current_time = datetime.now()
        new_time = current_time + timedelta(minutes=settings.ORDER_TIMEOUT)
        exp_time = new_time.strftime("%Y-%m-%d %H:%M:%S")
        logger.info(f"设置超时时间{exp_time}")

        ##获取默认地址
        logger.info("获取默认地址")
        receive_data = await OrdersReceive.filter(user_id=user_id, is_default=1).first().values()
        if receive_data:
            receive_id = receive_data.get("id")
            receive_name = receive_data.get("receive_name")
            receive_phone = receive_data.get("receive_phone")
            receive_address = receive_data.get("receive_address")
        else:
            receive_id = 0
            receive_name = ''
            receive_phone = ''
            receive_address = ''
        water_no = self.generate_order_number()
        order_data = {
            "user_id": user_id,
            "goods": goods,
            "price": price,
            "amount_price": price,
            "type": type,
            "address_id": address_id,
            "exp_time": exp_time,
            "express_price": 0.00,
            "receive_name": receive_name,
            "receive_phone": receive_phone,
            "receive_address": receive_address,
            "water_no": water_no,
        }
        order_in = OrdersListCreate(**order_data)

        ##拿到订单id后创建订单明细
        try:
            # 使用事务确保订单、商品和库存更新的原子性
            async with in_transaction() as transaction:
                # 创建订单

                ret = await self.create(obj_in=order_in)
                if not ret:
                    return {"pay_status": 0, "msg": "创建订单失败"}

                # 获取订单 ID 并插入订单商品数据
                goods = ret.goods
                for good in goods:
                    goods_data = {
                        "order_id": ret.id,
                        "user_id": user_id,
                        "goods_id": good.get('goods_id'),
                        "price": good.get('price'),
                        "sale_price": 0.00,
                        "sale_roles": None,
                        "num": good.get('num'),
                        "attr": good.get('attr', None),
                        "status": 0,
                        "sku_id": good.get('sku_id'),
                        "sku_name": good.get('sku_name'),
                        "is_express": 0,
                        "express_name": "待发货",
                        "express_company": "",
                        "express_no": "",
                    }
                    goods_in = OrdersGoodsCreate(**goods_data)
                    await orders_goods_controller.do_create(goods_in)

                    # 更新库存操作放入事务中执行
                    await GoodsSku.filter(id=good.get('sku_id')).update(sku_kc=good.get('kc_now') - good.get('num'))

                logger.info("计算运费")
                ##计算运费
                if receive_id > 0:
                    await self.get_express_price(order_id=ret.id, receive_id=receive_id)
                ##10分钟后执行查询未付款
                logger.info("10分钟后执行查询未付款")
                scheduler.add_func_job(f"order_{ret.id}", self.order_timeout, settings.ORDER_TIMEOUT + 1,
                                       f"order_{ret.id}", ret.id)
                logger.info(f"下单成功{ret.id}")
                return {"pay_status": 1, "msg": "下单成功", "order_id": ret.id}
        except Exception as e:
            logger.info(f"订单创建过程中发生错误{e}")
            return {"pay_status": 0, "msg": f"订单创建过程中发生错误{e}"}

    ##计算运费和设置发货地址
    @staticmethod
    async def get_express_price(order_id, receive_id):
        price = 0.00
        ##获取地址
        receive_data = await OrdersReceive.filter(id=receive_id).first().values()
        await OrdersList.filter(id=order_id).update(
            express_price=price,
            receive_name=receive_data.get("receive_name"),
            receive_phone=receive_data.get("receive_phone"),
            receive_address=receive_data.get("receive_address"),
        )
        return True

    ##判断是否需要抽奖
    @staticmethod
    async def is_need_draw(order_id, order_type):
        is_draw = 0
        try:
            draw_setting = await MiniSettings.filter(id=3).first().values("is_active")
            if draw_setting:
                if draw_setting['is_active'] == True and order_type == 1:
                    is_draw = 1
                    logger.info(f"订单id:{order_id},可以抽奖")
        except Exception as e:
            logger.info(f"订单id:{order_id},抽奖状态查询失败{e}")
        return is_draw

    ##支付成功回调
    async def order_success(self, out_trade_no, order_id: int = 0):
        if order_id > 0:
            order = await OrdersList.filter(id=order_id).first().values()
        else:
            order = await OrdersList.filter(water_no=out_trade_no).first().values()
        order_id = order['id']
        logger.info(f"订单id:{order_id}开始回调")
        order_status = order['status']
        ##支付回调检测余额和优惠券是否足够支付
        check = await self.check_asset_after(order_id)
        if check["pay_status"] == 0:
            return check
        logger.info(f"订单id:{order_id},足够支付")
        is_draw = await self.is_need_draw(order_id, order["type"])
        if order_status == 0:
            try:
                # 使用事务确保订单、商品和库存更新的原子性
                async with in_transaction() as transaction:
                    # 设置订单的状态为1
                    current_time = datetime.now()
                    pay_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
                    ##查询是否可以抽奖
                    await OrdersList.filter(id=order_id).update(status=1, pay_time=pay_time, is_draw=is_draw)
                    # 是否需要生成发货待办
                    # 扣除使用的储值金和优惠券
                    if order["deposit_price"] > 0:
                        logger.info(f"使用储值金")
                        deposit_data = DepositCreate(
                            user_id=order["user_id"],
                            price=order["deposit_price"],
                            direction=2,
                            order_id=order_id,
                            goods_id=0,
                            order_goods_id=0,
                            goods_num=0,
                            remark=order["remark"]
                        )
                        await deposit_controller.do_create(obj_in=deposit_data)

                    if order["coupons_price"] > 0:
                        logger.info(f"使用优惠券")
                        coupon_ids = {coupons['id'] for coupons in order["coupons"]}
                        await Coupons.filter(id__in=coupon_ids).update(is_used=1, order_id=order_id)

                    # 检测商品是否生成资产
                    goods = await OrdersGoods.filter(order_id=order_id).all().values()
                    for good in goods:
                        goods_id = good.get('goods_id')
                        sku_id = good.get('sku_id')
                        num = good.get('num')
                        goods_data = await Goods.filter(id=goods_id).first().values()
                        if goods_data['get_deposit'] and goods_data['get_deposit_max']:
                            # 获得储值金
                            logger.info(f"获得储值金")
                            money = random.randint(goods_data['get_deposit'], goods_data['get_deposit_max'])

                            p = good.get('price')  ##这里应该是
                            zs_money = (money-p) * num  ##赠送金额 = 随机充值金 - 订单总金额
                            deposit_data = DepositCreate(
                                user_id=order["user_id"],
                                price=float(money * num),
                                zs_price=float(zs_money),
                                direction=1,
                                order_id=order_id,
                                goods_id=goods_id,
                                order_goods_id=good.get('id'),
                                goods_num=good.get('num'),
                                remark=order["remark"]
                            )
                            await deposit_controller.do_create(obj_in=deposit_data)
                        if goods_data['get_coupons']:
                            # 获得优惠券
                            logger.info(f"获得优惠券")
                            coupons = await CouponsRole.filter(id=goods_data['get_coupons'], state=1).first().values()
                            if coupons:
                                coupons_data = CouponsCreate(
                                    user_id=order["user_id"],
                                    coupons_id=coupons['id'],
                                    coupons_price=0,
                                    expire_at="",
                                    is_used=0,
                                    come_type=2,
                                    add_order_id=order_id,
                                    order_goods_id=goods_id,
                                    remark=order["remark"]
                                )
                                for i in range(num):
                                    await coupons_controller.do_create(obj_in=coupons_data)
                        if goods_data['get_integral']:
                            # 获得积分
                            logger.info(f"获得积分")
                            integral_data = IntegralCreate(
                                user_id=order["user_id"],
                                price=float(goods_data['get_integral'] * num),
                                direction=1,
                                type=1,
                                type_id=order_id,
                                remark=order["remark"]
                            )
                            await integral_controller.do_create(obj_in=integral_data)
                        if goods_data['get_level_integral']:
                            # 获得成长积分
                            logger.info(f"获得成长积分")
                            level_integral_data = LevelIntegralCreate(
                                user_id=order["user_id"],
                                price=float(goods_data['get_level_integral'] * num),
                                direction=1,
                                order_id=order["id"],
                                remark=f"订单编号:{order["id"]}生成"
                            )
                            await level_integral_controller.do_create(obj_in=level_integral_data)
                        if goods_data['is_buckling'] == 1:
                            ##如果是划扣商品，添加划扣内容
                            logger.info(f"添加划扣内容")
                            sku_data = await GoodsSku.filter(id=sku_id).first().values("can_do")
                            if sku_data:
                                can_do = sku_data["can_do"]
                                if can_do > 0:
                                    buckling_in = BucklingCreate(
                                        order_id=order_id,
                                        goods_id=goods_id,
                                        sku_id=sku_id,
                                        user_id=order["user_id"],
                                        nums=can_do * num,
                                        direction=1,
                                        add_uid=0,
                                        space_id=order["address_id"],
                                        use_nums=0,
                                        last_nums=can_do * num
                                    )
                                    await buckling_controller.do_create(obj_in=buckling_in)

                    if order["type"] == 3:
                        ##储值订单直接发货成功
                        await OrdersList.filter(id=order_id).update(is_express=1)
                    ##如果是预约订单，设置预约状态为1
                    if order["type"] == 1:
                        await appointment_list_controller.do_success(order_id=order_id)
                    ##分享奖励
                    if order["type"] == 1 or order["type"] == 2:
                        if order["price"] >=200:
                            # 获得优惠券
                            logger.info(f"获得邀请奖励优惠券")
                            parent = await CustomerUser.filter(id=order["user_id"]).first().values("parent_id","name")
                            if parent:
                                coupons_data = CouponsCreate(
                                    user_id=parent["parent_id"],
                                    coupons_id=8,
                                    coupons_price=0,
                                    expire_at="",
                                    is_used=0,
                                    come_type=4,
                                    add_order_id=order_id,
                                    order_goods_id=0,
                                    remark=f"用户{parent["name"]},订单号:{order_id}的邀请奖励"
                                )
                                await coupons_controller.do_create(obj_in=coupons_data)

                    # 推送给云打印机/广播
                    try:
                        await manager.notify_clients(f"您有一个新的订单:{order_id}")
                    except Exception as e:
                        # 捕获并记录异常
                        logger.info(f"推送失败: {e}")
                        return False

                    logger.info(f"订单回调成功{order_id}")
                    return {"pay_status": 1, "msg": "成功"}
            except Exception as e:
                logger.info(f"订单回调过程中发生错误{order_id}: {e}")
                return {"pay_status": 0, "msg": f"订单回调过程中发生错误: {e}"}
        return {"pay_status": 1, "msg": "成功"}

    ##检测是否足够支付[支付后回调检测]
    @staticmethod
    async def check_asset_after(order_id: int):
        order = await orders_list_controller.do_get(data_id=order_id)
        deposit_price = order['deposit_price']
        is_deposit = order["is_deposit"]
        coupons = order["coupons"]
        user_id = order['user_id']
        if coupons:
            for coupon_item in coupons:
                coupon_data = await coupons_controller.do_detail(data_id=coupon_item["id"])
                if coupon_data['is_used'] == 1:
                    return {"pay_status": 0, "msg": f"检测到优惠券id:{coupon_item["id"]}已经用过了"}
        if is_deposit == 1:
            user_deposit = await users_controller.update_money(type=1, user_id=user_id)
            if deposit_price > user_deposit:
                return {"pay_status": 0, "msg": "余额不足支付"}
        return {"pay_status": 1, "msg": "检测通过"}

    @staticmethod
    def generate_order_number():
        # 获取当前日期
        now = datetime.now()
        # 格式化为 YYYYMMDD_HHMMSS_随机数
        order_number = now.strftime("%Y%m%d%H%M%S") + str(now.microsecond)[:3]
        ##单号为str类型
        dh = f"czs{order_number}"
        return dh

    ##订单取消2退款4调用
    @staticmethod
    async def order_refund(order_id: int, order_status: int):
        if order_status == 1:
            await OrdersList.filter(id=order_id).update(status=order_status)
        else:
            order = await OrdersList.filter(id=order_id).first().values()
            order_id = order['id']
            user_id = order['user_id']
            now_status = order['status']
            if now_status < 2:
                try:
                    async with in_transaction() as transaction:
                        logger.info("查询用户剩余资产")
                        customers_asset = await CustomerUser.filter(id=user_id).first().values()
                        ##储值记录
                        result = await Deposit.filter(order_id=order_id, direction=1).annotate(
                            add_price=Sum('price')
                        ).first()
                        if result.add_price:
                            ##计算除开生成的这些，余额会不会是负数，如果是负数则无法退款
                            if customers_asset["money_deposit"] < result.add_price:
                                return {"refund_status": 0, "msg": "储值金不够扣除"}
                        ##优惠券
                        result = await Coupons.filter(add_order_id=order_id, is_used=1).all().values()
                        if result:
                            return {"refund_status": 0, "msg": "有优惠券已经使用了"}
                        ##积分
                        result = await Integral.filter(type_id=order_id, direction=1).annotate(
                            add_price=Sum('price')
                        ).first()
                        if result.add_price:
                            if customers_asset["money_integral"] < result.add_price:
                                return {"refund_status": 0, "msg": "积分不够扣除"}
                        ##成长积分
                        result = await LevelIntegral.filter(order_id=order_id, direction=1).annotate(
                            add_price=Sum('price')
                        ).first()
                        if result.add_price:
                            if customers_asset["level_integral"] < result.add_price:
                                return {"refund_status": 0, "msg": "成长积分不够扣除"}

                        ##已开卡划扣
                        result = await Buckling.filter(order_id=order_id, use_nums__gt=0).first()
                        if result:
                            return {"refund_status": 0, "msg": "已经存在开卡的项目,请先移除划扣记录"}

                        ##取消预约
                        await AppointmentList.filter(order_id=order_id).delete()

                        await Deposit.filter(order_id=order_id).delete()  ##删除生成的储值金和使用的储值金
                        await users_controller.update_money(type=1, user_id=user_id)
                        await Coupons.filter(add_order_id=order_id).delete()  ##删除生成的优惠券
                        await Coupons.filter(order_id=order_id).update(is_used=0, order_id=0, order_goods_id=0,
                                                                       remark=None)  ##修改使用的优惠券为未使用
                        await users_controller.update_money(type=3, user_id=user_id)
                        await Integral.filter(type_id=order_id).delete()  ##删除生成的积分
                        await users_controller.update_money(type=2, user_id=user_id)
                        await LevelIntegral.filter(order_id=order_id).delete()  ##删除生成的成长积分
                        await users_controller.update_money(type=5, user_id=user_id)
                        await Buckling.filter(order_id=order_id).delete()  ##删除生成耗卡
                        ##库存回滚，通过order_goods
                        goods = await OrdersGoods.filter(order_id=order_id).values("sku_id", "num")
                        if goods:
                            for good in goods:
                                await GoodsSku.filter(id=good.get('sku_id')).update(
                                    sku_kc=F('sku_kc') + good.get('num'))
                        await OrdersGoods.filter(order_id=order_id).update(status=order_status)
                        current_time = datetime.now()
                        refund_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
                        await OrdersList.filter(id=order_id).update(status=order_status, refund_time=refund_time,
                                                                    is_draw=0)
                        ##支付退款
                        logger.info(f"进入微信支付退款{order_id}")
                        order_water = await OrdersWater.filter(order_id=order_id).first().values()
                        if order_water:
                            ret = wechat_controller.refund(
                                out_refund_no=order_water['out_trade_no'],
                                amount=order_water['amount'],
                                transaction_id=order_water['transaction_id'])
                            if ret['refund_status'] == 1:
                                await OrdersWater.filter(order_id=order_id).delete()
                                logger.info(f"微信支付退款完成{order_id}")
                                if order["type"] == 1:
                                    await appointment_list_controller.do_refund(order_id=order_id)
                                return {"refund_status": 1, "msg": "订单退款成功"}
                            else:
                                return {"refund_status": 0, "msg": "微信基本账户余额不足，请充值后重新发起"}
                        else:
                            if order["type"] == 1:
                                await appointment_list_controller.do_refund(order_id=order_id)
                            return {"refund_status": 1, "msg": "订单退款成功"}

                except Exception as e:
                    logger.info(f"订单退款过程中发生错误{order_id}:{e}")
                    return {"refund_status": 0, "msg": "订单退款过程中发生错误"}
        return {"refund_status": 1, "msg": "订单退款成功"}

    ##订单支付
    async def order_pay(self, data_in: OrdersListPay, pay_type: int = 0):
        order_id = data_in.id
        try:
            # 使用事务确保订单、商品和库存更新的原子性
            async with in_transaction() as transaction:
                await OrdersList.filter(id=order_id).update(
                    is_deposit=data_in.is_deposit,
                    coupons=data_in.coupons,
                )
                order = await orders_list_controller.do_get(data_id=order_id)
                if order["status"] != 0:
                    return {"pay_status": 0, "msg": f"订单已经{settings.ORDERS_STATUS[order["status"]]}"}
                price = order['price']
                is_deposit = order["is_deposit"]
                coupons = order["coupons"]
                user_id = order['user_id']
                ##计算优惠券合计金额
                coupons_price = 0.00
                deposit_price = 0.00
                last_price = float(price)
                sale_roles = []
                if coupons:  ##使用优惠券
                    for coupon_item in coupons:
                        coupon_data = await coupons_controller.do_detail(data_id=coupon_item["id"])
                        if user_id != coupon_data['user_id']:
                            return {"pay_status": 0, "msg": "不是自己的优惠券"}
                        if coupon_data['is_used'] == 1:
                            return {"pay_status": 0, "msg": f"优惠券id{coupon_item["id"]}已经用过了"}
                        datetime_obj = datetime.strptime(coupon_data['expire_at'], "%Y-%m-%d %H:%M:%S")
                        current_time = datetime.now()
                        if datetime_obj < current_time:
                            return {"pay_status": 0, "msg": "优惠券已经过期"}
                        coupon_rule_data = await coupons_rule_controller.do_detail(data_id=coupon_data['coupons_id'])
                        if coupon_rule_data["role"] > price:
                            return {"pay_status": 0, "msg": "使用起点不足"}
                        coupons_price += coupon_rule_data["value"]
                    if coupons_price < price:  ##优惠券不足够支付
                        last_price = float(price) - float(coupons_price)
                    else:
                        last_price = 0.00
                    sale_roles.append({"rule": f"优惠券抵扣了{coupons_price}元,"})
                if is_deposit == 1:  ##用了储值金
                    user_deposit = await users_controller.update_money(type=1, user_id=user_id)
                    if user_deposit >= last_price:
                        deposit_price = last_price
                        last_price = 0.00
                    else:
                        last_price = float(last_price) - float(user_deposit)
                        deposit_price = user_deposit
                    sale_roles.append({"rule": f"储值金抵扣了{deposit_price}元,"})
                sale_price = float(deposit_price) + float(coupons_price)
                await OrdersList.filter(id=order_id).update(
                    is_deposit=is_deposit,
                    deposit_price=deposit_price,
                    coupons=coupons,
                    coupons_price=coupons_price,
                    amount_price=last_price,
                    sale_price=sale_price,
                    sale_roles=sale_roles
                )
                if last_price == 0:  ##不需要再支付，直接支付成功
                    await self.order_success(out_trade_no=0, order_id=order_id)
                    logger.info(f"支付成功,资产足够直接抵扣{order_id}")
                    return {"pay_status": 1, "msg": "支付成功"}
                else:
                    if pay_type == 0:
                        ##去下单
                        total_fee = float(last_price) * 100
                        body = f"订单ID:{order_id}"
                        # out_trade_no = order["water_no"]
                        out_trade_no = self.generate_order_number()
                        user_openid = await CustomerUser.filter(id=user_id).first().values("open_id")
                        if user_openid["open_id"]:
                            ##更新一下订单号
                            logger.info(f"更新订单号{out_trade_no}")
                            update_result = await OrdersList.filter(id=order_id).update(water_no=out_trade_no)

                            if update_result:
                                logger.info(f"订单号 {order_id} 已更新为新的水单号: {out_trade_no}")
                                logger.info(
                                    f"进入微信支付:{order_id},需要支付的金额是:{total_fee},新订单号{out_trade_no}")
                                response = wechat_controller.pay(out_trade_no, math.ceil(total_fee), body,
                                                                 user_openid["open_id"])
                                return response
                            else:
                                logger.error(f"无法更新订单号为 {order_id} 的订单")
                                return {"pay_status": 0, "msg": f"无法更新订单号"}
                        else:
                            return {"pay_status": 0, "msg": f"未查到openid请重新登录"}
                    else:
                        logger.info(f"支付成功,线下收款")
                        await self.order_success(out_trade_no=0, order_id=order_id)
                        return {"pay_status": 1, "msg": "支付成功,线下收款"}

        except Exception as e:
            logger.info(f"订单支付过程中发生错误{order_id}: {e}")
            return {"pay_status": 0, "msg": f"订单回调过程中发生错误: {e}"}

    ##更新物流信息
    async def do_update(self, obj_in: OrdersListUpdate):
        try:
            # 更新订单
            ret = await self.update(id=obj_in.id, obj_in=obj_in)
            if not ret:
                return False  # 如果订单更新失败，则直接返回
            express_time = 0
            express_have = 0
            # 更新物流信息
            goods = ret.goods
            if not goods:  # 如果订单没有商品，直接返回
                return True
            # 遍历所有商品，更新物流信息
            for good in goods:
                express_time += 1
                is_express = 0
                if good.get('express_no'):  # 如果有物流单号，表示已经发货
                    is_express = 1
                    express_have += 1
                # 更新订单商品的发货信息
                await OrdersGoods.filter(id=good.get('id')).update(
                    is_express=is_express,
                    express_company=good.get('express_company'),
                    express_no=good.get('express_no')
                )
            # 判断是否全部发货
            if express_have == 0:
                is_express_all = 0  # 没有商品发货
            elif express_time == express_have:
                is_express_all = 1  # 全部发货
            else:
                is_express_all = 2  # 部分发货
            # 更新订单的发货状态
            await OrdersList.filter(id=ret.id).update(is_express=is_express_all)
            logger.info(f"更新物流信息成功{obj_in.id}")
            return True
        except Exception as e:
            # 捕获并记录异常
            logger.info(f"更新物流信息时发生错误: {e}")
            return False

    ##检测是否超时付款
    async def order_timeout(self, job_id, order_id):
        now = datetime.now(pytz.utc)  # 返回的是 datetime 对象，而不是字符串
        order = await OrdersList.filter(id=order_id).first().values()
        if order["exp_time"] <= now and order["status"] == 0:
            logger.info(f"任务:{job_id}检测超时订单:{order_id}")
            await self.order_refund(order_id=order_id, order_status=2)
        return True

    ##删除暂时不用
    async def do_delete(self, data_id: int, user_id: int, status: int):
        ##await self.model.filter(id=data_id).filter(user_id=user_id).update(status=status)
        return True

    @staticmethod
    async def do_can_edit(data_id: int):
        orders = await OrdersList.filter(id=data_id).first().values("status")
        status = orders["status"]
        if status > 0:
            return False
        return True

    @staticmethod
    # 获取当日业绩
    async def get_today_price():
        today = datetime.today().date()
        result = await OrdersList.filter(status=1).filter(created_at__gte=today).annotate(
            total_price=Sum('price')).first()
        total_price = float(result.total_price) if result.total_price else 0
        return total_price

    @staticmethod
    # 获取总业绩
    async def get_all_price():
        result = await OrdersList.filter(status=1).annotate(total_price=Sum('price')).first()
        total_price = float(result.total_price) if result.total_price else 0
        return total_price

    @staticmethod
    # 总订单数
    async def get_all_cnt():
        result = await OrdersList.filter(status=1).count()
        return result

    @staticmethod
    # 获取最近一周的日期范围
    def get_last_week_dates():
        today = datetime.today().date()
        start_date = today - timedelta(days=6)  # 上周一
        end_date = today  # 上周日
        return start_date, end_date

    # 一周的订单业绩
    async def get_weekly_order_totals(self):

        start_date, end_date = self.get_last_week_dates()
        orders = await OrdersList.filter(status=1).filter(created_at__gte=start_date).values('created_at', 'price')
        daily_totals = defaultdict(float)
        daily_nums = defaultdict(float)
        for order in orders:
            date = order['created_at'].date()
            daily_totals[date] += float(order['price']) if order['price'] else 0.0
            daily_nums[date] += 1

        result = []
        result_cnt = []
        current_date = start_date
        while current_date <= end_date:
            result.append(daily_totals.get(current_date, 0))
            result_cnt.append(daily_nums.get(current_date, 0))
            current_date += timedelta(days=1)
        return result, result_cnt

    @staticmethod
    # 一些数据
    async def get_goods_orders_datas():

        result = []
        # 库存预警:计算sku表库存小宇10的商品数量
        data1 = await GoodsSku.filter(sku_kc__lt=10).filter(sku_kc__gte=1).count()
        # 缺货下架
        data2 = await GoodsSku.filter(sku_kc=0).count()
        # 滞销商品
        data3 = await GoodsSku.filter(sku_kc__gte=100).count()
        # 待发货
        data4 = await OrdersList.filter(status=1, is_express=0).count()
        # 部分发货
        data5 = await OrdersList.filter(status=1, is_express=1).count()
        # 已经发货
        data6 = await OrdersList.filter(status=1, is_express=2).count()
        # 退款
        data7 = await OrdersList.filter(status=3).count()
        result += [data1, data2, data3, data4, data5, data6, data7]
        return result

    # 一周的UV
    async def get_weekly_uv(self):
        start_date, end_date = self.get_last_week_dates()
        uvs = await MiniAuditLog.filter(created_at__gte=start_date).values('created_at', 'user_id')
        daily_nums = defaultdict(float)
        for uv in uvs:
            date = uv['created_at'].date()
            daily_nums[date] += 1
        result = []
        current_date = start_date
        while current_date <= end_date:
            result.append(daily_nums.get(current_date, 0))
            current_date += timedelta(days=1)
        return result

    # UV比例
    @staticmethod
    async def get_uv_bl():
        today = datetime.today()
        start_of_day = datetime.combine(today, datetime.min.time())
        uvs = await MiniAuditLog.filter(created_at__gte=start_of_day).annotate(log_count=Count('user_id')).count()
        orders = await OrdersList.filter(created_at__gte=start_of_day).annotate(log_count=Count('user_id')).count()
        if uvs == 0:
            result = 0
        else:
            result = orders / uvs * 100
        return result

    # 一年的订单业绩
    @staticmethod
    async def get_monthly_order_totals():
        # 获取当前年份
        current_year = datetime.now().year
        start_date = datetime(current_year, 1, 1)  # 本年度的开始日期
        end_date = datetime(current_year + 1, 1, 1) - timedelta(days=1)  # 本年度的结束日期

        # 查询本年度的所有订单，状态为1（已完成）
        orders = await OrdersList.filter(status=1).filter(created_at__gte=start_date, created_at__lt=end_date).values(
            'created_at', 'price')

        # 用来存储每个月的订单金额合计
        monthly_totals = defaultdict(float)

        # 遍历订单，按月份累加金额
        for order in orders:
            month = order['created_at'].month  # 获取订单的月份
            monthly_totals[month] += float(order['price']) if order['price'] else 0.0

        # 准备返回的结果
        result = []
        for month in range(1, 13):  # 1 到 12 月
            result.append(monthly_totals.get(month, 0))  # 获取每月的总金额，如果没有订单则为 0

        return result


orders_list_controller = OrdersListController()
